/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * $Id: ConsultaDAO.java,v 1.10 
 * Universidad de los Andes (Bogotï¿½ - Colombia)
 * Departamento de Ingenierï¿½a de Sistemas y Computaciï¿½n 
 *
 * Ejercicio: TruequeAndes
 * Autor: Juan Diego Toro - 1-Marzo-2010
 * Ajustes : 2011
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
package co.edu.uniandes.truequeAndes.dao;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;

import co.edu.uniandes.truequeAndes.vos.Cliente;
import co.edu.uniandes.truequeAndes.vos.Producto;
import co.edu.uniandes.truequeAndes.vos.Producto2;
import co.edu.uniandes.truequeAndes.vos.Productoalterar;
import co.edu.uniandes.truequeAndes.vos.ValueClienteEnPaquete;
import co.edu.uniandes.truequeAndes.vos.ValueInt;
import co.edu.uniandes.truequeAndes.vos.ValueRF1;
import co.edu.uniandes.truequeAndes.vos.ValueRF2;
import co.edu.uniandes.truequeAndes.vos.ValueRF23;
import co.edu.uniandes.truequeAndes.vos.ValueRF3;
import co.edu.uniandes.truequeAndes.vos.ValueRF4;
import co.edu.uniandes.truequeAndes.vos.ValueRF6;
import co.edu.uniandes.truequeAndes.vos.ValueRF7;
import co.edu.uniandes.truequeAndes.vos.ValueRF8;
import co.edu.uniandes.truequeAndes.vos.ValueRF9;
import co.edu.uniandes.truequeAndes.vos.ValueUsuariosPerfil;
import co.edu.uniandes.truequeAndes.vos.ValuesOfertasDeCliente;

/**
 * Clase ConsultaDAO, encargada de hacer las consultas bï¿½sicas para el cliente
 */
public class ConsultaDAO {

	//----------------------------------------------------
	//Constantes
	//----------------------------------------------------
	/**
	 * ruta donde se encuentra el archivo de conexiï¿½n.
	 */
	private static final String ARCHIVO_CONEXION = "/../conexion.properties";



	//----------------------------------------------------
	//Atributos
	//----------------------------------------------------
	/**
	 * conexion con la base de datos
	 */
	public Connection conexion;

	/**
	 * nombre del usuario para conectarse a la base de datos.
	 */
	private String usuario="s2304a32";

	/**
	 * clave de conexiï¿½n a la base de datos.
	 */
	private String clave="awer123";

	/**
	 * URL al cual se debe conectar para acceder a la base de datos.
	 */
	private String cadenaConexion;

	/**
	 * constructor de la clase. No inicializa ningun atributo.
	 */
	public ConsultaDAO() 
	{  

	}


	//----------------------------------------------------
	//Consultas
	//----------------------------------------------------



	/**
	 * requerimiento 4
	 * 
	 */


	public Collection<ValueRF4> Requerimiento4() throws Exception
	{
		ArrayList<ValueRF4> retornar=new ArrayList<ValueRF4>();
		ValueRF4 valores=new ValueRF4();     
		PreparedStatement prepStmt = null;

		try
		{

			prepStmt = conexion.prepareStatement("select amostrar from (select PP.nombre, oo.id_producto_ofertado, oo.id_producto_demandado, level as nivelcito, sys_connect_by_path(nombre,'/') as amostrar from s2304a41.productos PP join s2304a41.ofertas_nociclicas OO on OO.ID_PRODUCTO_OFERTADO=PP.ID connect by nocycle prior OO.id_producto_demandado=OO.ID_PRODUCTO_OFERTADO)op join (select max(nivelcito) as nivel from (select PP.nombre, oo.id_producto_ofertado, oo.id_producto_demandado, level as nivelcito, sys_connect_by_path(nombre,'/') from s2304a41.productos PP join s2304a41.ofertas_nociclicas OO on OO.ID_PRODUCTO_OFERTADO=PP.ID connect by nocycle prior OO.id_producto_demandado=OO.ID_PRODUCTO_OFERTADO))gg on op.nivelcito=gg.nivel");
			ResultSet rs = prepStmt.executeQuery();



			while(rs.next())
			{
				String iterar=rs.getString("AMOSTRAR");
				String[] copiando=iterar.split("/");
				valores.setValor(copiando);
				retornar.add(valores);





				valores = new ValueRF4();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}

	/**
	 * obtiene ls datos necesarios para establecer una conexion
	 * Los datos se obtienen a partir de un archivo properties.
	 * @param path ruta donde se encuentra el archivo properties.
	 */
	public void inicializar()
	{
		try
		{
			//File arch= new File(path+ARCHIVO_CONEXION);
			//Properties prop = new Properties();
			//FileInputStream in = new FileInputStream( arch );

			//prop.load( in );
			//in.close( );

			cadenaConexion = "jdbc:oracle:thin:@chie.uniandes.edu.co:1521:chie10"; // El url, el usuario y passwd deben estar en un archivo de propiedades.
			// url: "jdbc:oracle:thin:@chie.uniandes.edu.co:1521:chie10";
			usuario = "s2304a32"; // "s2501aXX";
			clave = "awer123" ;// "c2501XX";

			final String driver = "oracle.jdbc.driver.OracleDriver";
			System.out.println(driver);

			Class.forName(driver);
			establecerConexion(cadenaConexion, usuario, clave);


		}
		catch(Exception e)
		{
			e.printStackTrace();
		} 
	}

	/**
	 * Metodo encargado de finalizar la conexion con la base de datos y liberando el recurso en memoria(conexion=null)
	 * @throws SQLException lanza excepcion en caso que exista problemas desconectandose.
	 */
	public void finalizar() throws SQLException
	{
		conexion.close();
		conexion=null;
	}



	/**
	 * Mï¿½todo que se encarga de crear la conexiï¿½n con el Driver Manager
	 * a partir de los parametros recibidos.
	 * @param url direccion url de la base de datos a la cual se desea conectar
	 * @param usuario nombre del usuario que se va a conectar a la base de datos
	 * @param clave clave de acceso a la base de datos
	 * @throws SQLException si ocurre un error generando la conexiï¿½n con la base de datos.
	 */
	private void establecerConexion(String url, String usuario, String clave) throws SQLException
	{
		try
		{
			conexion = DriverManager.getConnection(url,usuario,clave);
			System.out.println(conexion);
		}
		catch( SQLException exception )
		{
			System.out.println(exception.getCause());
			throw new SQLException( "ERROR: ConsultaDAO obteniendo una conexiï¿½n." );
		}
	}

	/**
	 *Cierra la conexiï¿½n activa a la base de datos. Ademï¿½s, con=null.
	 * @param con objeto de conexiï¿½n a la base de datos
	 * @throws SistemaCinesException Si se presentan errores de conexiï¿½n
	 */
	public void closeConnection(Connection connection) throws Exception {        
		try {
			connection.close();
			connection = null;
		} catch (SQLException exception) {
			throw new Exception("ERROR: ConsultaDAO: closeConnection() = cerrando una conexiï¿½n.");
		}
	} 

	// ---------------------------------------------------
	// Mï¿½todos asociados a los requerimientos Funcionales de  Consulta
	// ---------------------------------------------------


	/**
	 * Mï¿½todo que se encarga de realizar la consulta en la base de datos
	 * y retorna un elemento de tipo ClientesValue.
	 * @return ClienteValue cliente con el mayor nï¿½mero de productos ofertados en TruequeAndes. 
	 * @throws Exception se lanza una excepciï¿½n si ocurre un error en
	 * la conexiï¿½n o en la consulta. 
	 */
	public Collection<ValueRF1> darCantidadProductosPorCategoria() throws Exception
	{
		ArrayList<ValueRF1> retornar=new ArrayList<ValueRF1>();
		ValueRF1 valores=new ValueRF1();

		PreparedStatement prepStmt = null;

		try
		{
			prepStmt = conexion.prepareStatement("select C.nombre, count(OP.categoria) as cantidad from S2304A41.categorias C left join (select * from productos join ofertas on productos.id=ofertas.id_producto_ofertado)OP  on c.id=categoria group by C.nombre");
			ResultSet rs = prepStmt.executeQuery();


			while(rs.next())
			{
				String nombreCategoria = rs.getString("NOMBRE");
				int cantidad = Integer.parseInt(rs.getString("CANTIDAD"));


				valores.setNombre(nombreCategoria);
				valores.setCantidad(cantidad);
				retornar.add(valores);



				valores = new ValueRF1();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}



	/**
	 * CONSULTA BASICA PARA LOS NOMBRES DE LAS CATEGORIAS


	 */
	public Collection<Cliente> buscarCategorias() throws Exception
	{
		ArrayList<Cliente> retornar=new ArrayList<Cliente>();
		Cliente valores=new Cliente();

		PreparedStatement prepStmt = null;

		try
		{
			prepStmt = conexion.prepareStatement("select nombre as NOMBRE from categorias");
			ResultSet rs = prepStmt.executeQuery();


			while(rs.next())
			{
				String nombreCategoria = rs.getString("NOMBRE");
				valores.setEmail(nombreCategoria);

				retornar.add(valores);



				valores = new Cliente();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}


	/**
	 * consulta para la alteracion de datos basicos de los productos asociados al cliente registrado
	 * @param nCategoria
	 * @param orden
	 * @param organizado
	 * @return
	 * @throws Exception
	 */

	public Collection<Productoalterar> buscarProductosAsociadoClienteRF15(String email) throws Exception
	{
		ArrayList<Productoalterar> retornar=new ArrayList<Productoalterar>();
		Productoalterar valores=new Productoalterar();

		PreparedStatement prepStmt = null;

		try
		{
			prepStmt = conexion.prepareStatement("select idproducto, nombreproducto, valor, descripcion, valorcomercial, email, categorias.nombre from (select productos.id as idProducto, productos.categoria as idCategoria, productos.nombre as nombreProducto, productos.valor_estimado as valor, productos.descripcion as descripcion, productos.valor_comercial as valorComercial, productos.email_cliente as email from productos join clientes on productos.email_cliente=clientes.email where email='" + email + "')P join categorias on categorias.id=P.idcategoria");
			ResultSet rs = prepStmt.executeQuery();


			while(rs.next())
			{
				valores.setDescripcion(rs.getString("DESCRIPCION"));
				valores.setid(new BigInteger(rs.getString("IDPRODUCTO")));
				valores.setEmail(rs.getString("EMAIL"));
				valores.setNombre(rs.getString("NOMBREPRODUCTO"));
				valores.setValor(Integer.parseInt(rs.getString("VALOR")));
				valores.setValorComercial(Integer.parseInt(rs.getString("VALORCOMERCIAL")));
				valores.setCategoria("NOMBRE");





				retornar.add(valores);



				valores = new Productoalterar();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}




	/**
	 * consulta de los nombres de las categorias
	 */

	public Collection<Cliente> buscarnombreCategorias() throws Exception
	{
		ArrayList<Cliente> retornar=new ArrayList<Cliente>();
		Cliente valores=new Cliente();

		PreparedStatement prepStmt = null;

		try
		{
			prepStmt = conexion.prepareStatement("select nombre from categorias");
			ResultSet rs = prepStmt.executeQuery();


			while(rs.next())
			{
				valores.setEmail(rs.getString("NOMBRE"));





				retornar.add(valores);



				valores = new Cliente();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}

	/**
	 * consulta de productos del CLIENTE POR ID
	 */

	public Productoalterar buscarProductosId(String id) throws Exception
	{

		Productoalterar valores=new Productoalterar();

		PreparedStatement prepStmt = null;

		try
		{
			prepStmt = conexion.prepareStatement("select productos.nombre, productos.valor_estimado as valor, productos.descripcion, categorias.nombre as categoria, productos.valor_Comercial as valorComercial, productos.email_Cliente as email, productos.id as idproducto from productos join categorias on productos.categoria=categorias.id where productos.id='" + id +"'");
			ResultSet rs = prepStmt.executeQuery();

			int i=0;
			while(rs.next())
			{
				valores.setDescripcion(rs.getString(3));
				valores.setid(new BigInteger(rs.getString(7)));
				valores.setEmail(rs.getString(6));
				valores.setNombre(rs.getString(1));
				valores.setValor(Integer.parseInt(rs.getString(2)));
				valores.setValorComercial(Integer.parseInt(rs.getString(5)));
				valores.setCategoria(rs.getString(4));



				i++;






			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return valores;




	}







	/**
	 * 
	 */

	public Collection<ValueRF2> Requerimiento2(String nCategoria, boolean orden, String organizado) throws Exception
	{
		ArrayList<ValueRF2> retornar=new ArrayList<ValueRF2>();
		ValueRF2 valores=new ValueRF2();

		PreparedStatement prepStmt = null;

		try
		{
			String gg;
			if(orden)
				gg="asc";
			else
				gg="desc";
			prepStmt = conexion.prepareStatement("select nombreproducto, cantidad, productos.valor_estimado from productos join (select nombreproducto, cantidad from (select * from s2304a41.categorias left join (select count(*) as cantidad, nombre as nombreProducto, categoria from (select productos.nombre, productos.categoria from productos join ofertas on productos.id=ofertas.id_producto_ofertado) group by nombre, categoria)on categoria=categorias.id ) where nombre=' " + nCategoria + "' order by " + organizado +" " +  gg + ") on productos.nombre=nombreproducto");
			ResultSet rs = prepStmt.executeQuery();




			while(rs.next())
			{

				String nombreProducto = rs.getString("NOMBREPRODUCTO");
				int cantidad = Integer.parseInt(rs.getString("CANTIDAD"));
				int valorEstimado = Integer.parseInt(rs.getString("VALOR_ESTIMADO"));


				valores.setNombre(nombreProducto);
				valores.setCantidad(cantidad);
				valores.setValor(valorEstimado);
				retornar.add(valores);

				valores = new ValueRF2();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}





	/**
	 * rf3
	 */

	public Collection<ValueRF3> Requerimiento3(String busqueda, boolean orden, String organizado) throws Exception
	{
		ArrayList<ValueRF3> retornar=new ArrayList<ValueRF3>();
		ValueRF3 valores=new ValueRF3();

		PreparedStatement prepStmt = null;

		try
		{
			String gg;
			if(orden)
				gg="asc";
			else
				gg="desc";
			prepStmt = conexion.prepareStatement("select nombre_producto, cantidad, valor_estimado from productos join (select productos.nombre as nombre_producto, count(*) as cantidad from productos join ofertas on productos.id=ofertas.id_producto_ofertado group by productos.nombre) on productos.nombre=nombre_producto where nombre_producto LIKE '%"+busqueda+"%' order by "+ organizado + " " + gg );
			ResultSet rs = prepStmt.executeQuery();




			while(rs.next())
			{

				String nombreProducto = rs.getString("NOMBRE_PRODUCTO");
				int cantidad = Integer.parseInt(rs.getString("CANTIDAD"));
				int valorEstimado = Integer.parseInt(rs.getString("VALOR_ESTIMADO"));


				valores.setNombre(nombreProducto);
				valores.setCantidad(cantidad);
				valores.setValor(valorEstimado);
				retornar.add(valores);

				valores = new ValueRF3();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}

	/**
	 * consulta para productos propios del usuario buscados por login
	 * 
	 */

	public Collection<Producto2> BusquedaProductosPropios(String email) throws Exception
	{
		ArrayList<Producto2> retornar=new ArrayList<Producto2>();
		Producto2 valores=new Producto2();

		PreparedStatement prepStmt = null;

		try
		{

			prepStmt = conexion.prepareStatement("select P.idProducto, P.nombreProducto, P.valor from (select productos.id as idProducto, productos.nombre as nombreProducto, productos.valor_comercial as valor, clientes.email as cliente from productos join clientes on clientes.email=productos.email_cliente ) P where cliente='" + email + "'" );
			ResultSet rs = prepStmt.executeQuery();




			while(rs.next())
			{

				BigInteger idProducto =new BigInteger(rs.getString("IDPRODUCTO"));
				String nombre = rs.getString("NOMBREPRODUCTO");
				int valorComercial = Integer.parseInt(rs.getString("VALOR"));


				valores.setId(idProducto);
				valores.setNOmbre(nombre);
				valores.setValorComercial(valorComercial);
				retornar.add(valores);

				valores = new Producto2();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}



	/**
	 * CONSULTA PARA LAS OFERTAS KE NO SON PRODUCTOS DEL CLIENTE
	 * @param email
	 * @return
	 * @throws Exception
	 */


	public Collection<Producto2> BusquedaProductosDistintos(String email) throws Exception
	{
		ArrayList<Producto2> retornar=new ArrayList<Producto2>();
		Producto2 valores=new Producto2();

		PreparedStatement prepStmt = null;

		try
		{

			prepStmt = conexion.prepareStatement("Select  P.idproducto, P.nombreproducto, P.valor from (Select  productos.id as idproducto, productos.nombre as nombreproducto, productos.valor_comercial as valor, clientes.email as email from productos join clientes on clientes.email=productos.email_cliente)P where P.email<>'" + email +"' ");
			ResultSet rs = prepStmt.executeQuery();




			while(rs.next())
			{

				BigInteger idProducto = new BigInteger(rs.getString("IDPRODUCTO"));
				String nombre = rs.getString("NOMBREPRODUCTO");
				int valorComercial = Integer.parseInt(rs.getString("VALOR"));


				valores.setId(idProducto);
				valores.setNOmbre(nombre);
				valores.setValorComercial(valorComercial);
				retornar.add(valores);

				valores = new Producto2();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}

	/**
	 * rf6
	 */

	public Collection<ValueRF6> Requerimiento6() throws Exception
	{
		ArrayList<ValueRF6> retornar=new ArrayList<ValueRF6>();
		ValueRF6 valores=new ValueRF6();

		PreparedStatement prepStmt = null;

		try
		{

			prepStmt = conexion.prepareStatement("select * from clientes join (select *  from  (Select count(*) as cantidad, email_cliente from (select * from productos join ofertas on productos.id=ofertas.id_producto_ofertado)  group by email_cliente order by cantidad desc) where rownum='1') on email_cliente=clientes.email ");
			ResultSet rs = prepStmt.executeQuery();




			while(rs.next())
			{
				String email=rs.getString("EMAIL");
				String nickname = rs.getString("NICKNAME");
				String pais =rs.getString("PAIS");
				String nombre=rs.getString("NOMBRE");
				int cantidad=Integer.parseInt(rs.getString("CANTIDAD"));


				valores.setCantidad(cantidad);
				valores.setEmail(email);
				valores.setNickname(nickname);
				valores.setPais(pais);
				valores.setNombreCliente(nombre);
				retornar.add(valores);



				valores = new ValueRF6();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}






	/**
	 * rf7
	 */


	public Collection<ValueRF7> Requerimiento7() throws Exception
	{
		ArrayList<ValueRF7> retornar=new ArrayList<ValueRF7>();
		ValueRF7 valores=new ValueRF7();

		PreparedStatement prepStmt = null;

		try
		{

			prepStmt = conexion.prepareStatement("select p.nombre, client.nombre as Nombre_Cliente, cat.nombre as Nombre_Categoria from ofertas o,clientes client, categorias cat, productos p,(select min (o.fecha) as minimo from ofertas o )l where o.fecha=l.minimo and cat.id=p.categoria and p.id=o.id_producto_ofertado and p.email_cliente= client.email ");
			ResultSet rs = prepStmt.executeQuery();



			while(rs.next())
			{
				String nombre=rs.getString("NOMBRE");
				String nombreCliente=rs.getString("NOMBRE_CLIENTE");
				String nombreCategoria=rs.getString("NOMBRE_CATEGORIA");

				valores.setNombreCategoria(nombreCategoria);
				valores.setNombreCliente(nombreCliente);
				valores.setNombreProducto(nombre);
				retornar.add(valores);




				valores = new ValueRF7();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}




	/**
	 * rf8
	 */



	public Collection<ValueRF8> Requerimiento8(String fecha1, String fecha2) throws Exception
	{
		ArrayList<ValueRF8> retornar=new ArrayList<ValueRF8>();
		ValueRF8 valores=new ValueRF8();

		PreparedStatement prepStmt = null;

		try
		{

			prepStmt = conexion.prepareStatement("select categorias.nombre, FT.nombre, FT.cantidad  from categorias join (select *  from (select OP.*, ofertas.fecha from ofertas join  (select productos.categoria, GG.nombre, id, GG.cantidad from productos join (select nombre, count(*) as cantidad from (select * from productos join ofertas on ofertas.id_producto_ofertado=productos.id) group by nombre)GG on GG.nombre=productos.nombre)OP on OP.id=ofertas.id_producto_ofertado) OV   where OV.fecha>' " + fecha1 + "' and OV.fecha < '" + fecha2 + "' order by nombre) FT on categoria=categorias.id");
			ResultSet rs = prepStmt.executeQuery();



			while(rs.next())
			{
				String nombreProducto=rs.getString("NOMBREPRODUCTO");
				String nombre=rs.getString("NOMBRE");
				int cantidad=Integer.parseInt(rs.getString("CANTIDAD"));

				valores.setCantidad(cantidad);
				valores.setCategoria(nombre);
				valores.setProducto(nombreProducto);
				retornar.add(valores);


				valores = new ValueRF8();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}


	/**
	 * rf9
	 */

	public Collection<ValueRF9> Requerimiento8() throws Exception
	{
		ArrayList<ValueRF9> retornar=new ArrayList<ValueRF9>();
		ValueRF9 valores=new ValueRF9();

		PreparedStatement prepStmt = null;

		try
		{

			prepStmt = conexion.prepareStatement("select nombre, maxima,dia from categorias join (select OP.maxima, OP.dia, OP.categoria from (select max(cantidad) as maxima, dia, categoria from (select count(*) as cantidad,dia, categoria from (select  categoria, extract(day from fecha) as dia from productos join ofertas on productos.id=ofertas.id_producto_ofertado) group by dia, categoria) group by categoria, dia)OP join (select max(cantidad) as maxima, categoria from (select count(*) as cantidad,dia, categoria from (select  categoria, extract(day from fecha) as dia from productos join ofertas on productos.id=ofertas.id_producto_ofertado) group by dia, categoria) group by categoria)GG on OP.categoria=GG.categoria and OP.maxima=GG.maxima) on categorias.id=categoria ");
			ResultSet rs = prepStmt.executeQuery();



			while(rs.next())
			{
				String nombre=rs.getString("NOMBRE");
				int maxima=Integer.parseInt(rs.getString("MAXIMA"));
				int dia=Integer.parseInt(rs.getString("DIA"));

				valores.setDia(dia);
				valores.setCantidad(maxima);
				valores.setNombre(nombre);
				retornar.add(valores);




				valores = new ValueRF9();

			}
		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}

		finally {
			if (prepStmt != null) {
				try {
					prepStmt.close();
				} catch (SQLException exception) {

					exception.printStackTrace();
				}
			}

		}  
		return retornar;




	}

	public Connection darConexion ()
	{
		return conexion;
	}

	public boolean requerimiento11 (String pass, String email, String fechaNacimiento, String nickname, char genero)
	{
		PreparedStatement prepStmt = null;
		try 
		{
			prepStmt = conexion.prepareStatement("insert into clientes (password, email, fecha_nacimiento, fecha_registro, nickname, genero) values ('"+pass +"','"+email+"',sysdate, sysdate, '"+nickname+"','"+genero+"')");

			int i=prepStmt.executeUpdate();
			conexion.commit();
			prepStmt.close();

			return true;
		} 
		catch (SQLException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally 
		{



			return false;
		}


	}
	public boolean requerimiento12 (String nombre, String valorEstimado, String valorComercial, String categoria, String descripcion, String cliente)
	{

		PreparedStatement prepStmt = null;
		try 
		{
			prepStmt = conexion.prepareStatement("insert into productos(id, nombre,valor_estimado,categoria,descripcion,email_cliente, valor_comercial ) values	((select max(productos.id)+1 from productos), '"+nombre+"', "+valorEstimado + ",(select categorias.id from categorias where categorias.nombre= '"+categoria+"'),'"+descripcion+"' , '"+cliente+"',"+valorComercial +")" );
			int i=prepStmt.executeUpdate();
			if (i==0)
			{
				conexion.commit();
				prepStmt.close();

				return false;

			}
			else
				return true;
		}
		catch (SQLException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;

		}
		finally
		{
			return false;
		}

	}
	public boolean requerimento13 (BigInteger idDemandado, BigInteger idOfertado)
	{
		try 
		{
			PreparedStatement prepStmt = null;
			prepStmt = conexion
			.prepareStatement("insert into ofertas (id, id_producto_demandado, id_producto_ofertado, fecha, estado)values ((select max(ofertas.id)+1 from ofertas), "
					+ idDemandado
					+ ", "
					+ idOfertado
					+ ", sysdate, 'pendiente'");
			int i = prepStmt.executeUpdate();
			prepStmt.close();
			return true;
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
			return false;
		}
	}

	public boolean requerimiento14 (int idDemandado, int idOfertado)
	{
		try {
			PreparedStatement prepStmt = null;
			prepStmt = conexion
			.prepareStatement("update ofertas set estado='cancelada' where ofertas.id_producto_demandado="
					+ idDemandado);
			int i = prepStmt.executeUpdate();
			prepStmt = conexion
			.prepareStatement("update ofertas set estado='cancelada' where ofertas.id_producto_ofertado="
					+ idDemandado);
			i = prepStmt.executeUpdate();
			prepStmt = conexion
			.prepareStatement("update ofertas set estado='cancelada' where ofertas.id_producto_demandado="
					+ idOfertado);
			i = prepStmt.executeUpdate();
			prepStmt = conexion
			.prepareStatement("update ofertas set estado='cancelada' where ofertas.id_producto_ofertado="
					+ idOfertado);
			i = prepStmt.executeUpdate();
			prepStmt = conexion
			.prepareStatement("update ofertas set estado ='aceptada' where ofertas.id_producto_demandado= "
					+ idDemandado
					+ " and ofertas.id_producto_ofertado=" + idOfertado);
			i = prepStmt.executeUpdate();
			prepStmt.close();
			return true;
		} catch (Exception e)
		{
			e.printStackTrace();
			return false;
		}


	}

	public boolean requerimiento15 (String categoria, double valorEstimado, double valorComercial, BigInteger id)
	{

		try 

		{
			PreparedStatement prepStmt = null;
			prepStmt = conexion.prepareStatement("update productos set categoria= (select categorias.nombre from categorias where categorias.nombre= '"+categoria+"'), valor_estimado= "+valorEstimado+", valor_comercial= "+valorComercial+" where productos.id="+id);

			int i = prepStmt.executeUpdate();
			conexion.commit();
			prepStmt.close();
			return true;

		} 
		catch (SQLException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	public boolean requerimento16 (String emailCliente)
	{
		try
		{
			PreparedStatement prepStmt = null;
			prepStmt = conexion.prepareStatement("delete productos p where p.id in (select m.id from(select months_between (sysdate ,o.fecha) as resta, o.id_producto_ofertado as id from ofertas o, productos p  where o.estado='pendiente' and p.id= o.id_producto_ofertado and p.email_cliente= '"+emailCliente+"')m where m.resta<12 or m.resta=12)");
			int i= prepStmt.executeUpdate();
			prepStmt.close();
			return true;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return false;
		}
	}




	public boolean registrar(String login, String pass)
	{
		try {
			PreparedStatement prepStmt=null;
			prepStmt = conexion.prepareStatement("select * from clientes  where email ='" + login +"' and password='"+pass+"' ");
			ResultSet algo=prepStmt.executeQuery();
			return algo.next();





		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}


	//-----------------
	//NIVEL 3
	//-----------------

	/**
	 * Metodo encargado de ejecutar la secuencia sql para cambiar el estado de las ofertas y contraofertas 
	 * involucradas dentro de un rango de fechas para un usuario. 
	 * Se aplica como control de concurrencia un candado 
	 * @param correo El correo del usuario
	 * @param fechaInicial El string que representa la fecha inicial
	 * @param fechaFinal El String que representa la fecha final.
	 * @throws SQLException Lanza una excepcion en caso que exista una falla en la ejecucion de la sentencia.
	 */
	public void requerimiento21 (String correo, String fechaInicial, String fechaFinal) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("update ofertas set estado= 'cancelada' where id in (select l.id from (select o.id, o.fecha from ofertas o, paquetes p, productos pro where o.id=p.idoferta and p.idproducto= pro.id and pro.email_cliente= '"+correo+"' order by o.id, p.idpaquete,fecha , rol)l where l.fecha>='"+fechaInicial+"' and l.fecha<='"+fechaFinal+"')");
		int x=prep.executeUpdate();
		prep= conexion.prepareStatement("commit");
		boolean res=prep.execute();

		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion de R21 fue de "+ tfinal+"nanosegundos");
	}

	/**
	 * Metodo encargado de actualizar el valor estimado de un producto dado su id. 
	 * El valor solo es actualizado en el caso en que el producto este unicamente en ofertas cuyo estado sea pendiente
	 * @param idProducto el id del producto
	 * @param valorEstimado el valor estimando que se quiere actulizar
	 * @throws SQLException lanza excepcion en caso que la ejecucion no sea transaccional, no se actualicen tuplas o
	 * exista algun tipo de error en la ejecucion de la transaccion.
	 */
	public void requerimiento22 (String idProducto, String valorEstimado) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep = conexion.prepareStatement("update productos set valor_estimado ="+valorEstimado+"  where id not in (select pro.id from ofertas o, productos pro, paquetes p where pro.id ="+idProducto+" and p.idproducto = pro.id and o.id=p.idoferta and o.estado not like 'pendiente') and id = "+idProducto);
		int x= prep.executeUpdate();
		prep= conexion.prepareStatement("commit");
		boolean res= prep.execute();

		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion de R22 fue de "+ tfinal+"nanosegundos");
		finalizar();

	}
	/**
	 * Metodo encargado de listar los productos registrados en el ultimo mes para un cliente.
	 * @param correo el correo del cliente 
	 * @return un arraylist con los values de los productos.
	 * @throws SQLException En caso que exista un problema en la ejecucion de la sentencia sql.
	 */
	public ArrayList<ValueRF23> requerimiento23 (String correo)throws SQLException
	{
		long inicio=System.nanoTime();
		ArrayList<ValueRF23> values = new ArrayList<ValueRF23>();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select * from (select months_between(sysdate, p.fecha) as meses,p.id, p.nombre, p.imagen, cat.nombre as nombreCategoria, p.descripcion, p.fecha, p.valor_comercial, p.valor_estimado from productos p, clientes c, categorias cat where c.email= p.email_cliente and cat.id=p.categoria and c.email= '"+correo+"' order by p.nombre asc)l where l.meses<1");
		ResultSet res= prep.executeQuery();
		while (res.next())
		{
			ValueRF23 v= new ValueRF23();
			v.setId(new BigInteger(res.getString(2)));
			v.setNombreProducto(res.getString(3));
			v.setCategoria(res.getString(4));
			v.setDescripcion(res.getString(5));
			v.setFecha(res.getString(5));
			v.setValorComercial(res.getString(6));
			v.setValorEstimado(res.getString(7));
			values.add(v);

		}
		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion de R23 fue de "+ tfinal+"nanosegundos");
		return values;
	}

	/**
	 * Metodo encargado de retornar el nivel maximo del hilo de ofertas contraofertas relacionado a un id pasado como parametro
	 * @param idOferta el id de la oferta, idOferta!=null, !id.equals("")
	 * @return un entero con el nivel de la oferta
	 * @throws SQLException lanza excepcion en caso que exista algun problema en la ejecucion de la consutla
	 */
	public int darNivelOfertas (String idOferta) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select max (l.nivel) as nivel from  (select o.id,o.ofertapasada, level as nivel from ofertas o start with o.id= "+idOferta+" connect by nocycle prior   o.ofertaPasada= o.id  )l");
		ResultSet res= prep.executeQuery();
		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion para encontrar el nivel de una oferta fue de "+ tfinal+"nanosegundos");
		return res.getInt(1);
	}

	/**
	 * Metodo encargado de retornar un arraylist de values con los correos de las distintas personas involucrados en un paquete 
	 * dado como parametro.
	 * @param idPaquete el paquete del que se consutla.
	 * @return un arraylist de ValueClienteEnPaquete
	 * @throws SQLException lanza excepcion en caso que exista algun problema con la ejecucion de la sentencia sql
	 */
	public ArrayList<ValueClienteEnPaquete> darClientesEnOferta (String idPaquete) throws SQLException
	{
		long inicio=System.nanoTime();
		ArrayList<ValueClienteEnPaquete> values= new ArrayList<ValueClienteEnPaquete>();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select distinct pro.email_cliente from paquetes p , productos pro where p.idproducto= pro.id and p.idpaquete="+idPaquete+" and p.rol ='ofertado'");
		ResultSet res= prep.executeQuery();
		while (res.next())
		{
			ValueClienteEnPaquete e= new ValueClienteEnPaquete();
			e.setCorreo(res.getString(1));
			values.add(e);
		}
		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion para encontrar los clientes involucrados en una oferta fue de  "+ tfinal+"nanosegundos");

		return values;
	}


	/**
	 * Metodo encargado de retornar los productos que hacen parte un paquete y este ultimo es ofertado
	 * @param idPaquete el id del paquete de interes.
	 * @return un arraylist con los values de los productos.
	 * @throws SQLException Lanza excepcion en caso que exista algun problema en la ejecucion de la consulta.
	 */
	public ArrayList<ValueRF23> darProductosOfertadosEnPaquete (String idPaquete) throws SQLException
	{
		long inicio=System.nanoTime();
		ArrayList<ValueRF23> values = new ArrayList<ValueRF23>();
		inicializar();
		PreparedStatement prep= 
			conexion.prepareStatement("select pro.id, pro.nombre, pro.descripcion, pro.valor_Estimado, pro.valor_comercial ,cat.nombre as categoria, pro.fecha , pro.imagen,p.rol  from productos pro, paquetes p, categorias cat where p.idproducto= pro.id and p.rol='ofertado' and cat.id=pro.categoria and ="+idPaquete);
		ResultSet res= prep.executeQuery();
		while (res.next())
		{
			ValueRF23 v= new ValueRF23();
			v.setId(new BigInteger(res.getString(1)));
			v.setNombreProducto(res.getString(2));
			v.setCategoria(res.getString(6));
			v.setDescripcion(res.getString(3));
			v.setFecha(res.getString(7));
			v.setValorComercial(res.getString(5));
			v.setValorEstimado(res.getString(4));
			values.add(v);

		}
		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion de dar los productos ofertados en un paquete fue de "+ tfinal+"nanosegundos");
		return values;

	}

	/**
	 * Metodo encargado de retornar los productos que hacen parte un paquete y este ultimo es demandado
	 * @param idPaquete el id del paquete de interes.
	 * @return un arraylist con los values de los productos.
	 * @throws SQLException Lanza excepcion en caso que exista algun problema en la ejecucion de la consulta.
	 */
	public ArrayList<ValueRF23> darProductosDemandadosEnPaquete (String idPaquete) throws SQLException
	{
		long inicio=System.nanoTime();
		ArrayList<ValueRF23> values = new ArrayList<ValueRF23>();
		inicializar();
		PreparedStatement prep= 
			conexion.prepareStatement("select pro.id, pro.nombre, pro.descripcion, pro.valor_Estimado, pro.valor_comercial ,cat.nombre as categoria, pro.fecha , pro.imagen,p.rol  from productos pro, paquetes p, categorias cat where p.idproducto= pro.id and p.rol='demandado' and cat.id=pro.categoria and ="+idPaquete);
		ResultSet res= prep.executeQuery();
		while (res.next())
		{
			ValueRF23 v= new ValueRF23();
			v.setId(new BigInteger(res.getString(1)));
			v.setNombreProducto(res.getString(2));
			v.setCategoria(res.getString(6));
			v.setDescripcion(res.getString(3));
			v.setFecha(res.getString(7));
			v.setValorComercial(res.getString(5));
			v.setValorEstimado(res.getString(4));
			values.add(v);

		}
		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion de dar los productos ofertados en un paquete fue de "+ tfinal+"nanosegundos");

		return values;

	}


	/**
	 * Genera una nueva oferta. 
	 * @param ofertaPasada id que identifica la oferta pasada, este puede ser null.
	 * @throws SQLException lanza excepcion en caso que exista algun problema en la ejecucion de la sentencia, no se actualicen tuplas o
	 * exista algun tipo de error en la ejecucion de la transaccion.
	 * 
	 */
	public void generarNuevaOferta (String ofertaPasada) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("insert into ofertas (id, fecha, ofertapasada, estado ) values ((select max(id) from ofertas)+1, sysdate, "+ofertaPasada+", 'pendiente' )");
		int x=prep.executeUpdate();
		prep= conexion.prepareStatement("commit");
		boolean res=prep.execute();

		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion para generar una nueva oferta fue de  "+ tfinal+"nanosegundos");

		finalizar();

	}

	/**
	 * Metodo encargado de adicionar un conjunto de productos sobre un paquete nuevo
	 * @param idProducto el id del producto que se quiere adicionar , ids!=null, ids.size()>=1
	 * @throws SQLException lanza excepcion en caso que haya algun problema de transaccionalidad o en la ejecucion de la consutla sql
	 */
	public void adicionarSobrePaquete (ArrayList<String> ids) throws SQLException
	{
		long inicio=System.nanoTime();
		PreparedStatement prep =null;
		inicializar();
		boolean b ;
		for (int i = 0; i < ids.size(); i++)
		{
			boolean a = false;

			if (i==0)
			{
				prep = conexion.prepareStatement("insert into paquetes (idpaquete, idoferta, idproducto) values ((select max (idPaquete) from paquetes)+1, select max (idOferta),"+ids.get(i)+" );");	
				a=prep.execute();
				if (!a)
				{
					throw new SQLException("No se completo la transaccion");
				}
			}
			else
			{
				prep = conexion.prepareStatement("insert into paquetes (idpaquete, idoferta, idproducto) values ((select max (idPaquete) from paquetes), select max (idOferta),"+ids.get(i)+" );");	
				a= prep.execute();
				if (!a)
				{
					throw new SQLException("No se completo la transaccion");
				}
			}


		}
		prep= conexion.prepareStatement("commit");
		b=prep.execute(); 

		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion para adicionar un paquete de productos fue de  "+ tfinal+"nanosegundos");

		finalizar();

	}

	/**
	 * Metodo encargado de retornar las ofertas y contraofertas en las cuales se encuentra involucrado un cliente 
	 * @param correo el correo del cliente
	 * @return un arraylist de values con los ids de las ofertas y contraofertas.
	 * @throws SQLException En caso que exista algun problema en la ejecucion de la sentencia.
	 */
	public ArrayList<ValuesOfertasDeCliente> darOfertasDeCliente (String correo) throws SQLException
	{
		long inicio=System.nanoTime();
		ArrayList<ValuesOfertasDeCliente> ofertas = new ArrayList<ValuesOfertasDeCliente>();
		inicializar();
		PreparedStatement prep = conexion.prepareStatement("select o.id from ofertas o, paquetes p , productos pro where o.id=p.idoferta and p.idProducto=pro.id and pro.email_cliente ='"+correo+"'");
		ResultSet res = prep.executeQuery();
		while (res.next())
		{
			ValuesOfertasDeCliente v = new ValuesOfertasDeCliente();
			v.setIdOferta(res.getString(1));
			ofertas.add(v);
		}

		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion para dar las ofertas de un cliente fue de:  "+ tfinal+"nanosegundos");

		return ofertas;

	}
	/**
	 * acepta la oferta
	 */
	public void aceptarOferta (String idOferta) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();

		PreparedStatement prep= conexion.prepareStatement("update ofertas set estado='cancelada' where id in (select o.id from ofertas o start with o.id= "+idOferta+" connect by nocycle prior  o.ofertaPasada= o.id) or id in (select o.ofertapasada from ofertas o start with o.id= "+idOferta+" connect by nocycle prior  o.ofertaPasada= o.id)");
		int x=prep.executeUpdate();
		prep= conexion.prepareStatement("update ofertas set estado='aceptada' where id ="+idOferta);
		int y = prep.executeUpdate();
		boolean  p =prep.execute("commit");

		prep=conexion.prepareStatement("select distinct pro.email_cliente from ofertas o, paquetes p, productos pro where o.id="+ idOferta+"and p.rol='demandado' and  o.id=p.idOferta and pro.id=p.idProducto)");	
		ResultSet res= prep.executeQuery();

		String correoIni =res.getString(1);

		prep=conexion.prepareStatement("select distinct pro.email_cliente from ofertas o, paquetes p, productos pro where o.id="+ idOferta+"and p.rol='ofertado' and  o.id=p.idOferta and pro.id=p.idProducto)");	
		res=prep.executeQuery();
		String correoFin= res.getString(1);

		prep=conexion.prepareStatement("update productos set email_cliente ='"+correoFin+"' where id in (select pro.id from ofertas o, paquetes p, productos pro where o.id="+ idOferta+"and p.rol='demandado' and  o.id=p.idOferta and pro.id=p.idProducto)");	
		int z=prep.executeUpdate();
		prep=conexion.prepareStatement("update productos set email_cliente ='"+correoIni+"' where id in (select pro.id from ofertas o, paquetes p, productos pro where o.id="+ idOferta+"and p.rol='ofertado' and  o.id=p.idOferta and pro.id=p.idProducto)");	
		int u= prep.executeUpdate();

		prep= conexion.prepareStatement("commit");
		boolean k =prep.execute();

		finalizar();


		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion para aceptar una oferta fue de :  "+ tfinal+"nanosegundos");


	}
	/**
	 * da los productos del cliente demandado
	 * @param idOferta
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueRF23> darProductosClienteOfertado (String idOferta) throws SQLException
	{
		long inicio=System.nanoTime();
		ArrayList<ValueRF23> values = new ArrayList<ValueRF23>();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select p.id, p.nombre, p.valor_estimado, p.valor_comercial, p.descripcion, cat.nombre as categoria, p.fecha from productos p, categorias cat where email_cliente in (select pro.email_cliente from ofertas o, paquetes p, productos pro where  o.id= "+idOferta+" and p.rol='demandado' and  o.id=p.idOferta and pro.id=p.idProducto) and cat.id=p.categoria;");
		ResultSet res= prep.executeQuery();
		while (res.next())
		{
			ValueRF23 v= new ValueRF23();
			v.setId(new BigInteger(res.getString(1)));
			v.setNombreProducto(res.getString(2));
			v.setCategoria(res.getString(6));
			v.setDescripcion(res.getString(3));
			v.setFecha(res.getString(7));
			v.setValorComercial(res.getString(4));
			v.setValorEstimado(res.getString(5));
			values.add(v);

		}
		finalizar();
		long tfinal= System.nanoTime()- inicio;
		System.out.println("El tiempo de ejecucion para dar los productos de un cliente que aparece con una oferta(ofertado) es de "+ tfinal+"nanosegundos");

		return values;

	}



	/**
	 * metodo para buscar especificamente un idpaquete dado el id de la oferta
	 */

	public ValueInt darIdPaqueteDeOferta(String idOferta) throws SQLException
	{
		long inicio=System.nanoTime();
		PreparedStatement prepStmt = null;
		ValueInt valores=new ValueInt();
		try
		{
			prepStmt = conexion.prepareStatement(	"select  distinct(idpaquete) as idpaquete from ofertas join paquetes on paquetes.idoferta=ofertas.id where id=" + idOferta );
			ResultSet rs = prepStmt.executeQuery();


			valores.setNumero(Integer.parseInt(rs.getString("IDPAQUETE")));


		}
		catch(SQLException e)
		{
			e.printStackTrace();
		}
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para retornar un id de un paquete dado un id oferta es de " + tfinal + "nanosegundos");

		return valores;
	}

//TALLER 4
	
	
	/**
	 * metodo encargado de contar los usuarios gold
	 * @param intercambiosMax los intercambios maxima de la cual el usuario debe ser mayor  
	 * @param intercambiosMed los intercambios media de la cual el usuario debe ser mayor
	 * @return un arraylist con los valueUsuariosPerfil con los nicknames y paises de los usuarios que cumplen esos criterios
	 * @throws SQLException En caso de error inesperado
	 */
	public ArrayList<ValueInt> contarUsuariosGold (double intercambiosMax, double intercambiosMed) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from(select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas,(select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o ,(select p.idOferta, j.idPaquete, j.valor from paquetes p, (select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p, (select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado' )l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j  where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas>"+intercambiosMax+" and  gold.gananciapromedio>=0 and  gold.ofertasexitosas>"+intercambiosMed+" and gold.porcentajegananciapromedio>=0.8");
		ResultSet res =prep.executeQuery();
		ArrayList<ValueInt> a= new ArrayList<ValueInt>();
		while (res.next())
		{
			ValueInt v= new ValueInt();
			v.setNumero(Integer.parseInt(res.getString("NUMERO")));
			
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para contar los usuarios gold es de " + tfinal + " nanosegundos");
		return a;

	}

	/**
	 * metodo encargado de contar los usuarios premium
	 * @param intercambiosMax
	 * @param intercambiosMed
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueInt> contarUsuariosPremium (double intercambiosMed, double intercambiosMin) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas<"+intercambiosMed+" and gold.ofertasexitosas >"+intercambiosMin+" and porcentajegananciapromedio<0.8 and porcentajegananciapromedio>=0.4"); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueInt> a= new ArrayList<ValueInt>();
		while (res.next())
		{
			ValueInt v= new ValueInt();
			v.setNumero(Integer.parseInt(res.getString("NUMERO")));
			
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para contar los usuarios premium es de " + tfinal + " nanosegundos");
		return a;

	}

	/**
	 * metodo encargado contar los usuarios silver
	 * @param intercambiosMax
	 * @param intercambiosMed
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueInt> contarUsuariosSilver (double intercambiosMax, double intercambiosMed) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas< "+intercambiosMax+" and gold.ofertasexitosas >"+intercambiosMed+" and porcentajegananciapromedio<0.4 and porcentajegananciapromedio>=0.0"); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueInt> a= new ArrayList<ValueInt>();
		while (res.next())
		{
			ValueInt v= new ValueInt();
			v.setNumero(Integer.parseInt(res.getString("NUMERO")));
			
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para contar los usuarios silver es de " + tfinal + " nanosegundos");
		return a;

	}

	/**
	 * metodo encargado contar los usuarios copper
	 * @param intercambiosMed
	 * @param intercambiosMin
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueInt> contarUsuariosCopper (double intercambiosMed, double intercambiosMin) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas< "+intercambiosMed+" and gold.ofertasexitosas >"+intercambiosMin+" and porcentajegananciapromedio>=0.19"); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueInt> a= new ArrayList<ValueInt>();
		while (res.next())
		{
			ValueInt v= new ValueInt();
			v.setNumero(Integer.parseInt(res.getString("NUMERO")));
			
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para contar los usuarios coppper es de " + tfinal + " nanosegundos");
		return a;

	}
	
	/**
	 * metodo encargado de contar los usuarios sand
	 * @param intercambiosMed
	 * @param intercambiosMin
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueInt> contarUsuariosSand(double intercambiosMed, double intercambiosMin) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas< "+intercambiosMed+" and gold.ofertasexitosas >"+intercambiosMin+" and porcentajegananciapromedio<0.1 and porcentajegananciapromedio>=0.0"); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueInt> a= new ArrayList<ValueInt>();
		while (res.next())
		{
			ValueInt v= new ValueInt();
			v.setNumero(Integer.parseInt(res.getString("NUMERO")));
			
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para contar los usuarios sand es de " + tfinal + " nanosegundos");
		return a;

	}
	
	//CONTADOOOOOOOOOOOOOOOOOOOOOOOORES
	//contadores
	//CONTADOOOOOOOOOOOOOOOOOOOOOOOORES
	
	/**
	 * metodo encargado de consultar los usuarios del perfil gold con sus nicknames y paises de acuerdo a los valores pasados como parametros
	 * @param intercambiosMax los intercambios maxima de la cual el usuario debe ser mayor  
	 * @param intercambiosMed los intercambios media de la cual el usuario debe ser mayor
	 * @return un arraylist con los valueUsuariosPerfil con los nicknames y paises de los usuarios que cumplen esos criterios
	 * @throws SQLException En caso de error inesperado
	 */
	public ArrayList<ValueUsuariosPerfil> darUsuariosGold (double intercambiosMax, double intercambiosMed) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select * from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from(select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas,(select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o ,(select p.idOferta, j.idPaquete, j.valor from paquetes p, (select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p, (select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado' )l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j  where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas>"+intercambiosMax+" and  gold.gananciapromedio>=0 and  gold.ofertasexitosas>"+intercambiosMed+" and gold.porcentajegananciapromedio>=0.8");
		ResultSet res =prep.executeQuery();
		ArrayList<ValueUsuariosPerfil> a= new ArrayList<ValueUsuariosPerfil>();
		while (res.next())
		{
			ValueUsuariosPerfil v= new ValueUsuariosPerfil();
			v.setNickname(res.getString("NICKNAME"));
			v.setPais(res.getString("PAIS"));
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para dar los usuarios gold es de " + tfinal + " nanosegundos");
		return a;

	}

	/**
	 * metodo encargado de buscar los usuarios de perfil premium
	 * @param intercambiosMax
	 * @param intercambiosMed
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueUsuariosPerfil> darUsuariosPremium (double intercambiosMax, double intercambiosMed) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select * from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas< "+intercambiosMax+" and gold.ofertasexitosas >"+intercambiosMed+" and porcentajegananciapromedio<0.8 and porcentajegananciapromedio>=0.4"); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueUsuariosPerfil> a= new ArrayList<ValueUsuariosPerfil>();
		while (res.next())
		{
			ValueUsuariosPerfil v= new ValueUsuariosPerfil();
			v.setNickname(res.getString("NICKNAME"));
			v.setPais(res.getString("PAIS"));
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para dar los usuarios premium es de " + tfinal + " nanosegundos");
		return a;

	}

	/**
	 * metodo encargado de buscar los usuarios de perfil silver
	 * @param intercambiosMax
	 * @param intercambiosMed
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueUsuariosPerfil> darUsuariosSilver (double intercambiosMax, double intercambiosMed) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select * from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas< "+intercambiosMax+" and gold.ofertasexitosas >"+intercambiosMed+" and porcentajegananciapromedio<0.4 and porcentajegananciapromedio>=0.0"); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueUsuariosPerfil> a= new ArrayList<ValueUsuariosPerfil>();
		while (res.next())
		{
			ValueUsuariosPerfil v= new ValueUsuariosPerfil();
			v.setNickname(res.getString("NICKNAME"));
			v.setPais(res.getString("PAIS"));
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para dar los usuarios silver es de " + tfinal + " nanosegundos");
		return a;

	}

	/**
	 * metodo encargado de buscar los usuarios de perfil copper
	 * @param intercambiosMed
	 * @param intercambiosMin
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueUsuariosPerfil> darUsuariosCopper (double intercambiosMed, double intercambiosMin) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select * from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas< "+intercambiosMed+" and gold.ofertasexitosas >"+intercambiosMin+" and porcentajegananciapromedio>=0.1 "); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueUsuariosPerfil> a= new ArrayList<ValueUsuariosPerfil>();
		while (res.next())
		{
			ValueUsuariosPerfil v= new ValueUsuariosPerfil();
			v.setNickname(res.getString("NICKNAME"));
			v.setPais(res.getString("PAIS"));
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para dar los usuarios copper es de " + tfinal + " nanosegundos");
		return a;

	}
	
	/**
	 * metodo encargado de buscar los usuarios sand
	 * @param intercambiosMed
	 * @param intercambiosMin
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueUsuariosPerfil> darUsuariosSand(double intercambiosMed, double intercambiosMin) throws SQLException
	{
		 long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas< "+intercambiosMed+" and gold.ofertasexitosas >"+intercambiosMin+" and porcentajeganaciapromedio<0.1 and porcentajegananciapromedio>=0.0"); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueUsuariosPerfil> a= new ArrayList<ValueUsuariosPerfil>();
		while (res.next())
		{
			ValueUsuariosPerfil v= new ValueUsuariosPerfil();
			v.setNickname(res.getString("NICKNAME"));
			v.setPais(res.getString("PAIS"));
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para dar los usuarios sand es de " + tfinal + " nanosegundos");
		return a;

	}
	
	
	/**
	 * 
	 */

	/**
	 * metodo encargado de contar los usuarios new
	 * @param intercambiosMin
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueInt> contarUsuariosNew (double intercambiosMin) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas <"+intercambiosMin+" and porcentajegananciapromedio>=0.0 "); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueInt> a= new ArrayList<ValueInt>();
		while (res.next())
		{
			ValueInt v= new ValueInt();
			v.setNumero(Integer.parseInt(res.getString("NUMERO")));
			
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para contar los usuarios new es de " + tfinal + " nanosegundos");
		return a;

	}


	/**
	 * metodo encargado de contar los usuarios naif
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueInt> contarUsuariosNaif () throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select count(*) as numero from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where porcentajegananciapromedio>0 "); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueInt> a= new ArrayList<ValueInt>();
		while (res.next())
		{
			ValueInt v= new ValueInt();
			v.setNumero(Integer.parseInt(res.getString("NUMERO")));
			
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para contar los usuarios naif es de " + tfinal + " nanosegundos");
		return a;

	}
	
	
	
//FIN
	/**
	 * metodo encargado de buscar los usuarios new
	 * @param intercambiosMin
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueUsuariosPerfil> darUsuariosNew (double intercambiosMin) throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select * from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where gold.ofertasexitosas <"+intercambiosMin+" and porcentajegananciapromedio>=0.0 "); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueUsuariosPerfil> a= new ArrayList<ValueUsuariosPerfil>();
		while (res.next())
		{
			ValueUsuariosPerfil v= new ValueUsuariosPerfil();
			v.setNickname(res.getString("NICKNAME"));
			v.setPais(res.getString("PAIS"));
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para dar los usuarios new es de " + tfinal + " nanosegundos");
		return a;

	}


	/**
	 * metodo encargado de buscar los usuarios naif
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<ValueUsuariosPerfil> darUsuariosNaif () throws SQLException
	{
		long inicio=System.nanoTime();
		inicializar();
		PreparedStatement prep= conexion.prepareStatement("select * from (select oferticas.nickname, oferticas.pais , avg(dinero.ganancia) as gananciaPromedio, avg(dinero.porcentaje) as porcentajegananciapromedio,  count(oferticas.id) as ofertasexitosas  from (select /*+ USE_HASH (p pro)*/ c.nickname, c.pais ,o.id, c.email from ofertas o, clientes c, paquetes p, productos pro where p.idoferta=o.id and p.idproducto=pro.id and pro.email_cliente=c.email )oferticas, (select o.id, (ofertados.valor-demandados.valor) as ganancia, ((ofertados.valor-demandados.valor)/demandados.valor) as porcentaje  from ofertas o , (select p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p,(select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='ofertado')l where p.idPaquete=l.idPaquete and p.rol='ofertado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='ofertado')ofertados, (select /*+ USE_HASH(p j) */p.idOferta, j.idPaquete, j.valor from paquetes p,(select p.idPaquete, sum(l.valor) as valor from paquetes p, (select p.idpaquete, pro.id, pro.valor_comercial as valor from paquetes p, productos pro where pro.id= p.idproducto and p.rol='demandado')l where p.idPaquete=l.idPaquete and p.rol='demandado' group by p.idPaquete)j where j.idPaquete=p.idpaquete and p.rol='demandado' )demandados where o.ofertapasada is null and o.estado='aceptada' and ofertados.idPaquete=demandados.idPaquete and o.id= demandados.idOferta and demandados.idOferta=ofertados.idOferta)dinero where oferticas.id=dinero.id group by oferticas.nickname, oferticas.pais, oferticas.email) gold where porcentajegananciapromedio>0 "); 
		ResultSet res =prep.executeQuery();
		ArrayList<ValueUsuariosPerfil> a= new ArrayList<ValueUsuariosPerfil>();
		while (res.next())
		{
			ValueUsuariosPerfil v= new ValueUsuariosPerfil();
			v.setNickname(res.getString("NICKNAME"));
			v.setPais(res.getString("PAIS"));
			a.add(v);
		}
		finalizar();
		long tfinal=System.nanoTime()-inicio;
		System.out.println("El tiempo de ejecucion para dar los usuarios naif es de " + tfinal + " nanosegundos");
		return a;

	}


	//-------------------------------------
	//Metodos encargados de poblar y construir las tablas
	//-------------------------------------

	/**
	 *Este metodo es de POBLAR
	 * Metodo encargado de retornar los ids de las ofertas en la base de datos.
	 * @throws SQLException 
	 */
	public ArrayList<String> darIdsOfertas () throws SQLException
	{
		inicializar();
		PreparedStatement prep = conexion.prepareStatement("select id from ofertas");
		ResultSet res = prep.executeQuery();
		ArrayList<String> a= new ArrayList<String>();
		while(res.next())
		{
			a.add(res.getString(1));
		}
		finalizar();
		return a;
	}

	/**
	 * Este metodo es de POBLAR
	 * Metodo encargado de seleccionar los diferentes paquetes asociados a una oferta pasada como parametro
	 * @param idOferta el id de la oferta
	 * @return retorna un arraylist con los strings de los ids de los paquetes
	 * @throws SQLException
	 */
	public ArrayList<String> darPaquetesEnOferta (String idOferta) throws SQLException
	{
		inicializar();
		PreparedStatement prep = conexion.prepareStatement("select unique p.idpaquete from paquetes p where p.idoferta="+idOferta);
		ResultSet res = prep.executeQuery();
		ArrayList<String> a= new ArrayList<String>();
		while(res.next())
		{
			a.add(res.getString(1));
		}
		finalizar();
		return a;
	}

	//	/**
	//	 * METODO DE POBLAR
	//	 * Metodo encargado de calcular la ganancia de una oferta pasada como parametro para un paquete dado como parametro y actualizar la
	//	 * tabla ofertas con dicho valor. Dicho calculo se realiza como ofertado - demandado para el valor comercial.
	//	 * @param idPaquete el id del paquete del cual se desea calcular la ganancia
	//	 * @return un double con el valor de la ganacia
	//	 * @throws SQLException
	//	 */
	//	public int calcularGananciaOferta (String idPaquete) throws SQLException
	//	{
	//		inicializar();
	//		// Parte del ofertado
	//		PreparedStatement prep = conexion.prepareStatement("select sum (l.valor_comercial) as sumaOfertados from(select pro.valor_comercial from productos pro, paquetes p where p.idproducto=pro.id and p.idpaquete ="+idPaquete+" and p.rol='ofertado')l");
	//		ResultSet res = prep.executeQuery();
	//		double ofertado= res.getDouble(1);
	//		
	//		//Parte del demandado
	//		 prep = conexion.prepareStatement("select sum (l.valor_comercial) as sumaOfertados from(select pro.valor_comercial from productos pro, paquetes p where p.idproducto=pro.id and p.idpaquete ="+idPaquete+" and p.rol='demandado')l");
	//		 res = prep.executeQuery();
	//		 double demandado= res.getDouble(1);
	//		
	//		
	//
	//		finalizar();
	//		return ofertado-demandado;
	//		
	//	}





}

